#ifndef __SYLAR_IOMANAGER_H__
#define __SYLAR_IOMANAGER_H__

#include "scheduler.h"
#include "timer.h"

namespace sylar {

// OManager模块是一个基于epoll的IO事件调度器
// 工作流程
// 1 注册一个事件 -> 2 等待事件就绪 -> 3 调度回调函数 -> 4 注销事件 -> 5 执行回调函数
class IOManager : public Scheduler, public TimerManager 
{
public:
    enum Event 
    {
        NONE = 0x0,  // 无事件
        READ = 0x1,  // 读事件，对应 EPOLLIN
        WRITE = 0x4  // 写事件，对应 EPOLLOUT
    };

private:
    // 文件描述符上下文
    // 每个文件描述符对应一个 FdContext
    // FdContext 包含读写事件的上下文信息
    struct FdContext 
    {
        // 事件上下文
        struct EventContext 
        {
            // 调度器
            Scheduler *scheduler = nullptr;
            // 回调协程
            std::shared_ptr<Fiber> fiber;
            // 回调函数
            std::function<void()> cb;
        };

        // 读事件上下文
        EventContext read; 
        // 写事件上下文
        EventContext write;
        int fd = 0;  // 文件描述符
        Event events = NONE;  // 注册的事件
        std::mutex mutex;  // 互斥锁

        EventContext& getEventContext(Event event);  // 获取事件上下文
        void resetEventContext(EventContext &ctx);  // 重置事件上下文
        void triggerEvent(Event event);  // 触发事件        
    };

public:
    IOManager(size_t threads = 1, bool use_caller = true, const std::string &name = "IOManager");
    ~IOManager();

    // 添加一个事件
    int addEvent(int fd, Event event, std::function<void()> cb = nullptr);
    // 删除事件
    bool delEvent(int fd, Event event);
    // 删除事件并触发其回调
    bool cancelEvent(int fd, Event event);
    // 删除所有事件并触发其回调
    bool cancelAll(int fd);

    static IOManager* GetThis();

protected:
    void tickle() override;  // 唤醒调度器
    
    bool stopping() override;  // 判断是否停止
    
    void idle() override;  // 空闲处理

    void onTimerInsertedAtFront() override;  // 定时器插入到队列头部时的处理

    void contextResize(size_t size);  // 调整上下文大小

private:
    int m_epfd = 0;  // epoll 文件描述符
    int m_tickleFds[2];  // fd[0] 读，fd[1] 写
    std::atomic<size_t> m_pendingEventCount = {0};  // 待处理事件计数
    std::shared_mutex m_mutex;  // 共享锁
    std::vector<FdContext *> m_fdContexts;  // 存储每个文件描述符的上下文
};

} // end namespace sylar

#endif
